// EOValue.cs
//
//  Copyright (C) 2008 Whitemice Consulting
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
using System;

namespace Whitemice.EOMono
{
  /// <summary>
  /// Base class for EOValues
  /// </summary>
  public abstract class EOValue : IEOValue
  {
    protected bool  isNull;
    
    public EOValue()
    {
      isNull = true;
    } // end ctor
    
    public override string ToString()
    {
      return String;
    }
    
    public abstract object Value 
    { 
      get; 
      set; 
    } // end Value
    
    public abstract string SQLValue();
    
    public bool IsNull 
    {
      get { return isNull; }
      set { isNull = value; }
    } // end IsNull
    
    /// <value>
    /// Inverse of IsNull
    /// </value>
    public bool HasValue
    {
      get { return (!(this.IsNull)); }
      set { this.IsNull = (!(value)); }
    } // end HasValue
    
    /// <value>
    /// Integer value of value
    /// </value>
    public virtual int? Integer
    {
      get
      {
        if(IsNull) return null;
        try
        {
          int v = Convert.ToInt32(Value);
          return v;
        } catch (Exception ex) 
          {
            return null; 
          }
      }
    } // end Integer
    
    /// <value>
    /// Double value of value
    /// </value>
    public virtual double? Float
    {
      get
      {
        if(IsNull) return null;
        try
        {
          double v = Convert.ToDouble(Value);
          return v;
        } catch (Exception ex) 
          {
            return null; 
          }
      }
    } // end Float
    
    /// <value>
    /// String value of value
    /// </value>
    public virtual string String
    {
      get
      {
        if(IsNull) return null;
        return Value.ToString();
      }
    } // end String      
    
    /// <summary>
    /// Factory method for new IEOValue object for the specified
    /// field of the given entity
    /// </summary>
    /// <param name="name">
    /// A <see cref="System.String"/>
    /// </param>
    /// <param name="entity">
    /// A <see cref="EOEntity"/>
    /// </param>
    /// <returns>
    /// A <see cref="IEOValue"/>
    /// </returns>
    public static IEOValue EOFieldValue(string name, EOEntity entity)
    {
      IEOValue v;
      object   d = entity.DefaultValue(name);
      
      if (entity.HasField(name))
      {
        switch(entity.KindOfField(name))
        {
          case "Serial": 
            v = EOSerialValue(); 
            break;
          case "Integer":
            if (d == null) v = EOIntegerValue(null); 
            else v = EOIntegerValue(Convert.ToInt32(d));
            break;
          case "String": 
            if (d == null) v = EOStringValue(null); 
            else v = EOStringValue(d.ToString());
            break;
          case "Float": 
            if (d == null) v = EONumericValue(null); 
            else v = EONumericValue(Convert.ToDouble(d));
            break;
          case "Double": 
            if (d == null) v = EONumericValue(null); 
            else v = EONumericValue(Convert.ToDouble(d));
            break;            
          case "Date": 
            v = EODateValue(); 
            break;
          case "DateTime": 
            v = EODateTimeValue();
            break;
          default:
            throw new EOUnknownKindException(entity.KindOfField(name));
        }
        return v;
      }
      throw new Exception("Entity has no such field");
    } // end EOFieldValue
    
    /// <summary>
    /// Factory a new String value
    /// </summary>
    /// <param name="v">
    /// A <see cref="System.String"/>
    /// </param>
    /// <returns>
    /// A <see cref="IEOValue"/>
    /// </returns>
    public static IEOValue EOStringValue(string v)
    {
      return new EOString(v);
    } // end EOStringValue
     
    /// <summary>
    /// Factory a new Numeric value
    /// </summary>
    /// <param name="v">
    /// A <see cref="System.Nullable`1"/>
    /// </param>
    /// <returns>
    /// A <see cref="IEOValue"/>
    /// </returns>
    public static IEOValue EONumericValue(double? v)
    {
      if (v.HasValue)
        return new EONumber((double)v);
      else return new EONumber();
    } // end EONumericValue
    
    /// <summary>
    /// Factory a new Integer Value
    /// </summary>
    /// <param name="v">
    /// A <see cref="System.Nullable`1"/>
    /// </param>
    /// <returns>
    /// A <see cref="IEOValue"/>
    /// </returns>
    public static IEOValue EOIntegerValue(int? v)
    {
      if (v.HasValue)
        return new EOInteger((int)v);
      else return new EOInteger();
    } // end EOIntegerValue
    
    /// <summary>
    /// Factory EOSerialValue
    /// </summary>
    /// <returns>
    /// A <see cref="IEOValue"/>
    /// </returns>
    public static IEOValue EOSerialValue()
    {
      return new EOSerial();
    } // end EOSerialValue
    
    /// <summary>
    /// Factory new Date Value
    /// </summary>
    /// <returns>
    /// A <see cref="IEOValue"/>
    /// </returns>
    public static IEOValue EODateValue()
    {
      return new EODate(); 
    } // end EODateVaue
    
    /// <summary>
    /// Factory new Date & Time Value
    /// </summary>
    /// <returns>
    /// A <see cref="EOValue"/>
    /// </returns>
    public static EOValue EODateTimeValue()
    {
      return new EODateTime();
    } // end EODateTimeValue
  } // end class
}
